package edu.hawaii.myisern.action;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import edu.hawaii.myisern.model.MyIsernModel;
import edu.hawaii.myisern.organizations.jaxb.AffiliatedResearchers;
import edu.hawaii.myisern.organizations.jaxb.Organization;
import edu.hawaii.myisern.organizations.jaxb.ResearchKeywords;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;


/**
 * Allows for a organization to be added or edited. 
 * 
 * @author Jon Lao
 * @author Jared Sunouchi
 * @author Chiao-Fen Zielinski-Liu
 */
public class OrganizationActionBean implements ActionBean {
  /** Required by the ActionBean interface. */
  private ActionBeanContext context;
  /** An error string, always displayed, but invisible if empty. */
  private String errorMessage = "";
  /** Add label and type. */
  private String addType;
  /** Edit label and type. */
  private String editType;
  /** Added? */
  private boolean added;
  /** Editing? */
  private boolean editing;
  /** Edited? */
  private boolean edited;
  /** The single MyIsern instance manipulated by all webapp users. */
  private MyIsernModel myIsern = MyIsernModel.getInstance();
  /** Researcher attributes */
  private String name;
  private String type;
  private String contact;
  private String affiliatedResearchers;
  private String country;
  private String researchKeywords;
  private String researchDescription;
  private String homePage;
  
  private String organization = "Organization";
  private List<String> organizationNames;
  
  /**
   * Returns the context. Required by the interface. 
   * 
   * @return the ActionBeanContext.
   */
  public ActionBeanContext getContext() {
    return context;
  }
  
  /**
   * Sets the context. Required by the interface. 
   * 
   * @param context The ActionBeanContext to set. 
   */
  public void setContext(ActionBeanContext context) {
    this.context = context;
  }
  
  /**
   * Returns the error message, which may be empty.
   * Indicates if an error was made adding or editing the organization. 
   * 
   * @return The error message. 
   */
  public String getErrorMessage() {
    return this.errorMessage;
  }
  
  /**
   * Returns the appropriate add label.
   * 
   * @return The add label. 
   */
  public String getAddType() {
    return this.addType;
  }
  
  /**
   * Returns the appropriate edit label.
   * 
   * @return The edit label. 
   */
  public String getEditType() {
    return this.editType;
  }
  
  /**
   * Returns the whether the organization has been added or not.
   * 
   * @return Whether the organization has been added or not. 
   */
  public boolean getAdded() {
    return this.added;
  }
  
  /**
   * Returns the whether the organization has been edited or not.
   * 
   * @return Whether the organization has been edited or not. 
   */
  public boolean getEdited() {
    return this.edited;
  }
  
  /**
   * Returns the whether the organization is being edited or not.
   * 
   * @return Whether the organization is being edited or not. 
   */
  public boolean getEditing() {
    return this.editing;
  }
  
  /**
   * Creates and returns the list of organization names.
   * 
   * @return The list of organization names.
   */
  public List<String> getOrganizationNames() {
    List<Organization> orgList = myIsern.getOrganizations();
    List<String> orgNamesList = new ArrayList<String>();
    for (Organization org : orgList) {
      orgNamesList.add(org.getName());
    }
    Collections.sort(orgNamesList);
    this.organizationNames = orgNamesList;
    
    return this.organizationNames;
  }
  
  /**
   * Displays the form to add a organization.
   * 
   * @return A Resolution indicating to redisplay the add.jsp page.
   */
  public Resolution organizationForm() {
    this.addType = organization;
    return new ForwardResolution("/add.jsp");
  }
  
  /**
   * Displays the form to edit an organization.
   * 
   * @return A Resolution indicating to redisplay the edit.jsp page.
   */
  public Resolution editOrganizationForm() {
    this.editType = organization;
    return new ForwardResolution("/edit.jsp");
  }
  
  /**
   * Sets the name of the organization.
   * 
   * @param name The name to set.
   */
  public void setName(String name) {
    this.name = name.trim();
  }
  
  /**
   * Returns the name of the organization.
   * @return The name of the organization.
   */
  public String getName() {
    return this.name;
  }
  
  /**
   * Sets the type of the organization.
   * 
   * @param type The type to set.
   */
  public void setType(String type) {
    this.type = type.trim();
  }
  
  /**
   * Returns the type of the organization.
   * @return The type of the organization.
   */
  public String getType() {
    return this.type;
  }
  
  /**
   * Sets the contact of the organization.
   * 
   * @param contact The contact to set.
   */
  public void setContact(String contact) {
    this.contact = contact.trim();
  }
  
  /**
   * Returns the contact of the organization.
   * 
   * @return The contact of the organization.
   */
  public String getContact() {
    return this.contact;
  }
  
  /**
   * Sets the affiliated researchers of the organization.
   * 
   * @param affiliatedResearchers  The researchers to set.
   */
  public void setAffiliatedResearchers(String affiliatedResearchers) {
    this.affiliatedResearchers = affiliatedResearchers;
  }
  
  /**
   * Returns the affiliated researchers of the organization.
   * 
   * @return The affiliated researchers of the organization.
   */
  public String getAffiliatedResearchers() {
    return this.affiliatedResearchers;
  }
  
  /**
   * Sets the country of the organization.
   * 
   * @param country The country to set.
   */
  public void setCountry(String country) {
    this.country = country.trim();
  }
  
  /**
   * Returns the country of the organization.
   * 
   * @return The country of the organization.
   */
  public String getCountry() {
    return this.country;
  }
  
  /**
   * Sets the research keywords of the organization.
   * 
   * @param researchKeywords  The keywords to set.
   */
  public void setResearchKeywords(String researchKeywords) {
    this.researchKeywords = researchKeywords;
  }
  
  /**
   * Returns the research keywords of the organization.
   * 
   * @return The research keywords of the organization.
   */
  public String getResearchKeywords() {
    return this.researchKeywords;
  }
  
  /**
   * Sets the research description of the organization.
   * 
   * @param researchDescription The research description to set.
   */
  public void setResearchDescription(String researchDescription) {
    this.researchDescription = researchDescription.trim();
  }
  
  /**
   * Returns the research description of the organization.
   * 
   * @return The research description of the organization.
   */
  public String getResearchDescription() {
    return this.researchDescription;
  }
  
  /**
   * Sets the home page of the organization.
   * 
   * @param homePage The home page to set.
   */
  public void setHomePage(String homePage) {
    this.homePage = homePage.trim();
  }
  
  /**
   * Returns the home page of the organization.
   * 
   * @return The home page of the organization.
   */
  public String getHomePage() {
    return this.homePage;
  }
  
  /**
   * Adds a organization.
   * 
   * @return A Resolution indicating to redisplay the add.jsp page.
   * @throws Exception If problems occur.
   */
  public Resolution add() throws Exception {
    if ((this.name == null) || ("".equals(this.name))) {
      this.errorMessage = "Please enter a name.";
    }
    else {
      List<Organization> list = myIsern.getOrganizations();
      boolean found = false;
      for (Organization organization : list) {
        if (organization.getName().equals(this.name.replace('_', ' '))) {
          found = true;
        }
      }
      
      if (found) {
        this.errorMessage = "Organization already exists. Please go to the edit page.";
      }
      else {
        Organization newOrganization = new Organization();
        newOrganization.setName(this.name);
        newOrganization.setType(this.type);
        newOrganization.setContact(this.contact);
        AffiliatedResearchers newAffiliatedResearchers = new AffiliatedResearchers();
        newAffiliatedResearchers.getAffiliatedResearcher()
        .addAll(myIsern.createList(this.affiliatedResearchers));
        newOrganization.setAffiliatedResearchers(newAffiliatedResearchers);
        newOrganization.setCountry(this.country);
        ResearchKeywords newResearchKeywords = new ResearchKeywords();
        newResearchKeywords.getResearchKeyword().addAll(myIsern.createList(this.researchKeywords));
        newOrganization.setResearchKeywords(newResearchKeywords);
        newOrganization.setResearchDescription(this.researchDescription);
        newOrganization.setHomePage(this.homePage);
        
        myIsern.addOrganization(newOrganization);
        
        this.added = true;
      }
    }
    this.addType = organization;
    return new ForwardResolution("/add.jsp");
  }
  
  /**
   * Displays the information to edit.
   * 
   * @return A resolution indicating to redisplay the edit.jsp page.
   * @throws Exception If problems occur.
   */
  public Resolution displayEdit() throws Exception {
    List<Organization> list = myIsern.getOrganizations();
    Organization editOrganization = new Organization();
    boolean found = false;
    for (Organization organization : list) {
      if (organization.getName().equals(this.name.replace('_', ' '))) {
        editOrganization = organization;
        found = true;
      }
    }

    if (found) {
      this.type = editOrganization.getType();
      this.contact = editOrganization.getContact();
      this.affiliatedResearchers = myIsern.createListString(editOrganization
          .getAffiliatedResearchers().getAffiliatedResearcher());
      this.country = editOrganization.getCountry();
      this.researchKeywords = myIsern.createListString(editOrganization.getResearchKeywords()
          .getResearchKeyword());
      this.researchDescription = editOrganization.getResearchDescription();
      this.homePage = editOrganization.getHomePage();

      this.editing = true;
    }
    
    this.editType = organization;
    return new ForwardResolution("/edit.jsp");
  }
  
  /**
   * Edits a organization.
   * 
   * @return A resolution indicating to redisplay the edit.jsp page.
   * @throws Exception If problems occur.
   */
  public Resolution edit() throws Exception {
    List<Organization> list = myIsern.getOrganizations();
    int count = 0;
    Organization editOrganization = new Organization();
    for (Organization organization : list) {
      if (organization.getName().equals(this.name.replace('_', ' '))) {
        editOrganization = organization;
        count = list.indexOf(organization);
      }
    }
    
    editOrganization.setType(this.type);
    editOrganization.setContact(this.contact);
    AffiliatedResearchers newAffiliatedResearchers = new AffiliatedResearchers();
    newAffiliatedResearchers.getAffiliatedResearcher()
        .addAll(myIsern.createList(this.affiliatedResearchers));
    editOrganization.setAffiliatedResearchers(newAffiliatedResearchers);
    editOrganization.setCountry(this.country);
    ResearchKeywords newResearchKeywords = new ResearchKeywords();
    newResearchKeywords.getResearchKeyword().addAll(myIsern.createList(this.researchKeywords));
    editOrganization.setResearchKeywords(newResearchKeywords);
    editOrganization.setResearchDescription(this.researchDescription);
    editOrganization.setHomePage(this.homePage);
    
    myIsern.editOrganization(count, editOrganization);
    
    this.edited = true;
    this.editing = true;
    this.editType = organization;    
    return new ForwardResolution("/edit.jsp");
  }
  
  /**
   * Removes the organization.
   * 
   * @return A resolution indicating to redisplay the add.jsp or edit.jsp page.
   * @throws Exception If problems occur.
   */
  public Resolution remove() throws Exception {    
    myIsern.removeOrganization(this.name);
    
    this.errorMessage = this.name + " has been removed.";
    return new ForwardResolution("/add.jsp");
  }
}
